%%%-------------------------------------------------------------------
%%% @author mirahs(2892727493@qq.com)
%%% @doc
%%%     类型相关工具
%%% @end
%%%-------------------------------------------------------------------
-module(util_type).

-export([
    to_atom/1
    ,to_list/1
    ,to_binary/1
    ,to_float/1
    ,to_integer/1
    ,list_to_atom/1

    ,term_to_bitstring/1
    ,bitstring_to_term/1

    ,ip_to_bitstring/1
    ,ip_to_bitstring/4
]).


%%%===================================================================
%%% API functions
%%%===================================================================

to_atom(Msg) when erlang:is_atom(Msg) -> Msg;
to_atom(Msg) when erlang:is_binary(Msg) -> ?MODULE:list_to_atom(binary_to_list(Msg));
to_atom(Msg) when erlang:is_integer(Msg) -> ?MODULE:list_to_atom(integer_to_list(Msg));
to_atom(Msg) when erlang:is_tuple(Msg) -> ?MODULE:list_to_atom(erlang:tuple_to_list(Msg));
to_atom(Msg) when erlang:is_list(Msg) ->
    Msg2 = list_to_binary(Msg),
    Msg3 = binary_to_list(Msg2),
    ?MODULE:list_to_atom(Msg3);
to_atom(_Data) -> ?MODULE:list_to_atom("").

%% 浮点数直接用 float_to_list(Float) 会用科学计数法表示并可能有误差，直接调用 float_to_list(Float, [{decimals, 长度}])
to_list(Data) when erlang:is_list(Data) -> Data;
to_list(Data) when erlang:is_atom(Data) -> atom_to_list(Data);
to_list(Data) when erlang:is_binary(Data) -> binary_to_list(Data);
to_list(Data) when erlang:is_integer(Data) -> integer_to_list(Data);
to_list(Data) when erlang:is_float(Data) -> float_to_list(Data);
to_list(_Data) -> [].

%% 浮点数直接用 float_to_list(Float) 会用科学计数法表示并可能有误差，直接调用 float_to_list(Float, [{decimals, 长度}])
to_binary(Data) when erlang:is_binary(Data) -> Data;
to_binary(Data) when erlang:is_atom(Data) -> list_to_binary(atom_to_list(Data));
to_binary(Data) when erlang:is_list(Data) -> list_to_binary(Data);
to_binary(Data) when erlang:is_integer(Data) -> list_to_binary(integer_to_list(Data));
to_binary(Data) when erlang:is_float(Data) -> float_to_binary(Data);
to_binary(_Data) -> <<>>.

%% 浮点数直接用 float_to_list(Float) 会用科学计数法表示并可能有误差，直接调用 float_to_list(Float, [{decimals, 长度}])
to_float(Data)->
    List = to_list(Data),
    list_to_float(List).

to_integer(Data) when erlang:is_integer(Data) -> Data;
to_integer(Data) when erlang:is_binary(Data) ->
    List = binary_to_list(Data),
    erlang:list_to_integer(List);
to_integer(Data) when erlang:is_list(Data) -> erlang:list_to_integer(Data);
to_integer(_Data) -> 0.

list_to_atom(List)->
    try
        erlang:list_to_existing_atom(List)
    catch _:_ ->
        erlang:list_to_atom(List)
    end.


%% [{name, mirahs}, {age, 18}] => <<"[{name,mirahs},{age,18}]">>
term_to_bitstring(Term) -> list_to_bitstring(io_lib:format("~w", [Term])).

%% <<"[{name,mirahs},{age,18}]">> => [{name, mirahs}, {age, 18}]
bitstring_to_term(BitString) ->
    String = binary_to_list(BitString),
    case erl_scan:string(String ++ ".") of
        {ok, Tokens, _} -> erl_parse:parse_term(Tokens);
        {error, Reason, _} -> {error, Reason}
    end.


ip_to_bitstring({N1, N2, N3, N4}) ->
    list_to_bitstring(lists:concat([N1, ".", N2, ".", N3, ".", N4])).
ip_to_bitstring(N1, N2, N3, N4) ->
    list_to_bitstring(lists:concat([N1, ".", N2, ".", N3, ".", N4])).
